Categories
MongoDB

Using MongoDB with Mongoose — Pre Middleware Errors and Post Middlewares

Spread the love

To make MongoDB database manipulation easy, we can use the Mongoose NPM package to make working with MongoDB databases easier.

In this article, we’ll look at how to use Mongoose to manipulate our MongoDB database.

Errors in Pre Hooks

We can raise errors in pre hooks in various ways.

For example, we can write:

async function run() {
  const { createConnection, Schema } = require('mongoose');
  const connection = createConnection('mongodb://localhost:27017/test');
  const schema  = new Schema({
    name: { type: String, required: true },
    age: Number
  });
  schema.pre('save', (next) => {
    const err = new Error('error');
    next(err);
  });
  const Kitten = connection.model('Kitten', kittenSchema);
}
run();

to pass an Error instance in the next method.

Also, we can return a promise:

async function run() {
  const { createConnection, Schema } = require('mongoose');
  const connection = createConnection('mongodb://localhost:27017/test');
  const kittenSchema = new Schema({
    name: { type: String, required: true },
    age: Number
  });
  schema.pre('save', (next) => {
    const err = new Error('error');
    return Promise.reject(err);
  });
  const Kitten = connection.model('Kitten', kittenSchema);
}
run();

Or we can throw an error:

async function run() {
  const { createConnection, Schema } = require('mongoose');
  const connection = createConnection('mongodb://localhost:27017/test');
  const schema = new Schema({
    name: { type: String, required: true },
    age: Number
  });
  schema.pre('save', (next) => {
    throw new Error('error');
  });
  const Kitten = connection.model('Kitten', kittenSchema);
}
run();

Post Middleware

Post middlewares are run after the hooked method and all its pre middleware are run.

For example, we can write:

async function run() {
  const { createConnection, Schema } = require('mongoose');
  const connection = createConnection('mongodb://localhost:27017/test');
  const schema = new Schema({
    name: { type: String, required: true },
    age: Number
  });
  schema.post('init', (doc) => {
    console.log('%s has been initialized from the db', doc._id);
  });
  schema.post('validate', (doc) => {
    console.log('%s has been validated (but not saved yet)', doc._id);
  });
  schema.post('save', (doc) => {
    console.log('%s has been saved', doc._id);
  });
  schema.post('remove', (doc) => {
    console.log('%s has been removed', doc._id);
  });
  const Kitten = connection.model('Kitten', kittenSchema);
}
run();

We added post middlewares for the init , validate , save , and remove operations that are run after the given document operations.

Async Post Hooks

We can add async post hooks. We just need to call next to proceed to the next post hook:

async function run() {
  const { createConnection, Schema } = require('mongoose');
  const connection = createConnection('mongodb://localhost:27017/test');
  const schema = new Schema({
    name: { type: String, required: true },
    age: Number
  });
  schema.post('save', (doc, next) => {
    setTimeout(() => {
      console.log('post1');
      next();
    }, 10);
  });

  schema.post('save', (doc, next) => {
    console.log('post2');
    next();
  });
  const Kitten = connection.model('Kitten', schema);
}
run();

We call the next function in the setTimeout callback to proceed to the next post middleware.

Define Middleware Before Compiling Models

We have to define middleware before we create the model with the schema for it to fire.

For example, we can write:

async function run() {
  const { createConnection, Schema } = require('mongoose');
  const connection = createConnection('mongodb://localhost:27017/test');
  const schema = new Schema({ name: String });
  schema.pre('save', () => console.log('pre save called'));
  const User = connection.model('User', schema);
  new User({ name: 'test' }).save();
}
run();

We created the schema and then added a save pre middleware right after we defined the schema and before the model is created.

This way, the callback in the pre method will be run when we create a document with the model.

Conclusion

We can add post middlewares and be careful where we define the model.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *